package com.tsfyun.scm.service.impl.wms;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Snowflake;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import com.tsfyun.common.base.enums.BaseDataTypeEnum;
import com.tsfyun.common.base.enums.BillTypeEnum;
import com.tsfyun.common.base.enums.InExpressTypeEnum;
import com.tsfyun.common.base.enums.domain.DomainOprationEnum;
import com.tsfyun.common.base.enums.domain.ReceivingNoteStatusEnum;
import com.tsfyun.common.base.exception.ServiceException;
import com.tsfyun.common.base.security.SecurityUtil;
import com.tsfyun.common.base.support.DomainStatus;
import com.tsfyun.common.base.util.StringUtils;
import com.tsfyun.common.base.util.TsfPreconditions;
import com.tsfyun.scm.dto.wms.ImpReceivingNoteDTO;
import com.tsfyun.scm.dto.wms.InspectionDTO;
import com.tsfyun.scm.dto.wms.ReceivingMemberSaveDTO;
import com.tsfyun.scm.dto.wms.ReceivingNoteQTO;
import com.tsfyun.scm.dto.wms.client.ClientReceivingNoteQTO;
import com.tsfyun.scm.entity.customer.Customer;
import com.tsfyun.scm.entity.customer.Supplier;
import com.tsfyun.scm.entity.order.ImpOrder;
import com.tsfyun.scm.entity.order.ImpOrderMember;
import com.tsfyun.scm.entity.order.OrderMemberReceivingNo;
import com.tsfyun.scm.entity.wms.ReceivingNote;
import com.tsfyun.scm.mapper.wms.ReceivingNoteMapper;
import com.tsfyun.scm.service.base.ISystemCacheService;
import com.tsfyun.scm.service.customer.ICustomerService;
import com.tsfyun.scm.service.customer.ISupplierService;
import com.tsfyun.scm.service.order.IImpOrderMemberService;
import com.tsfyun.scm.service.order.IImpOrderService;
import com.tsfyun.scm.service.order.IOrderMemberReceivingNoService;
import com.tsfyun.scm.service.system.IStatusHistoryService;
import com.tsfyun.scm.service.wms.IReceivingNoteMemberService;
import com.tsfyun.scm.service.wms.IReceivingNoteService;
import com.tsfyun.common.base.extension.ServiceImpl;
import com.tsfyun.scm.system.vo.BaseDataVO;
import com.tsfyun.scm.vo.storage.SimpleReceivingNoteCartonVO;
import com.tsfyun.scm.vo.wms.*;
import com.tsfyun.scm.vo.wms.client.ClientReceivingNoteVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;

/**
 * <p>
 * 入库单 服务实现类
 * </p>
 *
 *
 * @since 2020-04-24
 */
@Service
@Slf4j
public class ReceivingNoteServiceImpl extends ServiceImpl<ReceivingNote> implements IReceivingNoteService {

    @Autowired
    private ReceivingNoteMapper receivingNoteMapper;
    @Autowired
    private IReceivingNoteMemberService receivingNoteMemberService;
    @Autowired
    private ICustomerService customerService;
    @Autowired
    private ISupplierService supplierService;
    @Autowired
    private IStatusHistoryService statusHistoryService;
    @Autowired
    private ISystemCacheService systemCacheService;
    @Autowired
    private IImpOrderService impOrderService;
    @Autowired
    private IImpOrderMemberService impOrderMemberService;
    @Autowired
    private Snowflake snowflake;
    @Autowired
    private IOrderMemberReceivingNoService orderMemberReceivingNoService;

    @Override
    public PageInfo<ReceivingNoteListVO> pageList(ReceivingNoteQTO qto) {
        PageHelper.startPage(qto.getPage(),qto.getLimit());
        Map<String,Object> params = beanMapper.map(qto, Map.class);
        params.put("billType", BillTypeEnum.IMP.getCode());
        List<ReceivingNoteListVO> list = receivingNoteMapper.list(params);
        return new PageInfo<>(list);
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateReceivingNoteOrderNo(String docNo) {
        updateReceivingNoteOrderNo(findByDocNo(docNo));
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateReceivingNoteOrderNo(ReceivingNote receivingNote) {
        String orderNo = receivingNoteMapper.findReceivingNoteOrderNo(receivingNote.getDocNo());
        receivingNote.setOrderNo(StringUtils.isNotEmpty(orderNo)?orderNo:"");
        super.updateById(receivingNote);
    }

    @Override
    public ReceivingNotePlusDetailVO detail(Long id, String operation) {
        ReceivingNoteVO receivingNoteVO = mainDetail(id,operation);
        List<ReceivingNoteMemberVO> members = receivingNoteMemberService.findByReceivingNoteId(id);
        return new ReceivingNotePlusDetailVO(receivingNoteVO,members);
    }

    @Override
    public ReceivingNoteVO mainDetail(Long id, String operation) {
        ReceivingNoteVO receivingNoteVO = receivingNoteMapper.detail(id);
        Optional.ofNullable(receivingNoteVO).orElseThrow(()->new ServiceException("入库单不存在"));
        DomainStatus.getInstance().check(DomainOprationEnum.of(operation), receivingNoteVO.getStatusId());
        return receivingNoteVO;
    }

    @Override
    public InspectionNoteDetailVO inspectionDetail(Long id) {
        ReceivingNoteVO receivingNoteVO = receivingNoteMapper.detail(id);
        List<InspectionNoteMemberVO> inspectionMembers = receivingNoteMemberService.inspectionMembers(id);
        return new InspectionNoteDetailVO(receivingNoteVO,inspectionMembers);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long impRegister(ImpReceivingNoteDTO dto) {
        ReceivingNote receivingNote = beanMapper.map(dto,ReceivingNote.class);
        Customer customer = customerService.findByNameWithRight(dto.getCustomerName());
        receivingNote.setCustomerId(customer.getId());
        if(StringUtils.isNotEmpty(dto.getSupplierName())){
            Supplier supplier = supplierService.findByCustomerNameAndSupplierName(dto.getCustomerName(),dto.getSupplierName());
            TsfPreconditions.checkArgument(Objects.nonNull(supplier),new ServiceException("境外供应商不存在"));
            receivingNote.setSupplierId(supplier.getId());
        }
        receivingNote.setBillType(BillTypeEnum.IMP.getCode());
        ReceivingNoteStatusEnum statusEnum = ReceivingNoteStatusEnum.RECEIVED;
        receivingNote.setStatusId(statusEnum.getCode());
        BaseDataVO deliveryModeBaseData = systemCacheService.getBaseDataByTpeAndCode(BaseDataTypeEnum.DeliveryMode.getCode(),dto.getDeliveryMode());
        Optional.ofNullable(deliveryModeBaseData).orElseThrow(()->new ServiceException("交货方式错误"));
        receivingNote.setDeliveryMode(deliveryModeBaseData.getCode());
        receivingNote.setDeliveryModeName(deliveryModeBaseData.getName());
        receivingNote.setInExpressType("");
        receivingNote.setHkExpress("");
        receivingNote.setHkExpressName("");
        receivingNote.setHkExpressNo("");
        //快递入库
        if("ExpressDelivery".equals(receivingNote.getDeliveryMode())){
            InExpressTypeEnum inExpressTypeEnum = InExpressTypeEnum.of(dto.getInExpressType());
            Optional.ofNullable(inExpressTypeEnum).orElseThrow(()->new ServiceException("快递类型错误"));
            receivingNote.setInExpressType(inExpressTypeEnum.getCode());
            if(StringUtils.isNotEmpty(dto.getHkExpress())) {
                BaseDataVO HkExpress = systemCacheService.getBaseDataByTpeAndCode(BaseDataTypeEnum.HkExpress.getCode(),dto.getHkExpress());
                Optional.ofNullable(HkExpress).orElseThrow(()->new ServiceException("快递公司错误"));
                receivingNote.setHkExpress(HkExpress.getCode());
                receivingNote.setHkExpressName(HkExpress.getName());
            }
            //香港快递单号
            if(StringUtils.isNotEmpty(dto.getHkExpressNo())){
                //替换中文逗号
                receivingNote.setHkExpressNo(dto.getHkExpressNo().replace("，",","));
            }
        }
        try{
            super.saveNonNull(receivingNote);

            //按订单号入库
            if(StringUtils.isNotEmpty(receivingNote.getRegOrderNo())){
                ImpOrder impOrder = impOrderService.findByDocNo(receivingNote.getRegOrderNo());
                TsfPreconditions.checkArgument(Objects.nonNull(impOrder),new ServiceException(String.format("订单号【%s】不存在",receivingNote.getRegOrderNo())));
                TsfPreconditions.checkArgument(Objects.equals(receivingNote.getCustomerId(),impOrder.getCustomerId()),new ServiceException("订单与客户不匹配，请修改"));
                //写入订单绑定入库单辅助表
                List<ImpOrderMember> members = impOrderMemberService.getByOrderId(impOrder.getId());
                if(CollUtil.isNotEmpty(members)){
                    List<OrderMemberReceivingNo> orNos = Lists.newArrayList();
                    List<ImpOrderMember> updates = Lists.newArrayList();
                    members.stream().forEach(iom ->{
                        OrderMemberReceivingNo orderMemberReceivingNo = new OrderMemberReceivingNo();
                        orderMemberReceivingNo.setId(snowflake.nextId());
                        orderMemberReceivingNo.setOrderMemberId(iom.getId());
                        orderMemberReceivingNo.setReceivingNo(receivingNote.getDocNo());
                        orderMemberReceivingNo.setQuantity(iom.getQuantity());
                        orNos.add(orderMemberReceivingNo);

                        ImpOrderMember update = new ImpOrderMember();
                        update.setId(iom.getId());
                        update.setReceivingNoteNo(receivingNote.getDocNo());
                        update.setReceivingQuantity(iom.getQuantity());
                        updates.add(update);
                    });
                    if(CollUtil.isNotEmpty(orNos)){
                        //修改订单明细
                        impOrderMemberService.batchUpdatePartData(updates);
                        //添加绑定辅助表
                        orderMemberReceivingNoService.savaBatch(orNos);
                    }
                }

//                //订单明细同步入库明细
//                List<ImpOrderMember> impOrderMemberList =impOrderMemberService.getByOrderId(impOrder.getId());
//                if(CollUtil.isNotEmpty(impOrderMemberList)){
//                    //订单可绑定的明细数据
//                    UnboundDetailQTO qto = new UnboundDetailQTO();
//                    qto.setOrderNo(impOrder.getDocNo());
//                    Map<Long,UnboundDetailVO> unboundDetailVOMap = impOrderMemberService.unboundDetailList(qto).stream().collect(Collectors.toMap(UnboundDetailVO::getId, Function.identity()));
//
//                    List<ReceivingNoteMember> receivingNoteMemberList = Lists.newArrayList();
//                    List<OrderReceivingNoteMember> ornmList = Lists.newArrayList();
//                    impOrderMemberList.stream().forEach(iom ->{
//                        ReceivingNoteMember rnm = new ReceivingNoteMember();
//                        rnm.setId(snowflake.nextId());
//                        rnm.setReceivingNoteId(receivingNote.getId());
//                        rnm.setRowNo(iom.getRowNo());
//                        rnm.setModel(iom.getModel());
//                        rnm.setBrand(iom.getBrand());
//                        rnm.setName(iom.getName());
//                        rnm.setSpec(iom.getSpec());
//                        rnm.setGoodsCode(iom.getGoodsCode());
//                        rnm.setCountry(iom.getCountry());
//                        rnm.setCountryName(iom.getCountryName());
//                        rnm.setUnitCode(iom.getUnitCode());
//                        rnm.setUnitName(iom.getUnitName());
//                        rnm.setQuantity(iom.getQuantity());
//                        rnm.setNetWeight(iom.getNetWeight());
//                        rnm.setGrossWeight(iom.getGrossWeight());
//                        rnm.setCartonNo(iom.getCartonNo());
//                        rnm.setCartonNum(iom.getCartonNum());
//
//                        //绑定订单明细
//                        UnboundDetailVO detailVO = unboundDetailVOMap.get(iom.getId());
//                        if(Objects.nonNull(detailVO)){
//                            OrderReceivingNoteMember ornm = new OrderReceivingNoteMember();
//                            ornm.setId(snowflake.nextId());
//                            ornm.setOrderNo(impOrder.getDocNo());
//                            ornm.setOrderMemberId(detailVO.getId());
//                            ornm.setReceivingNo(receivingNote.getDocNo());
//                            ornm.setReceivingNoteMemberId(rnm.getId());
//                            ornm.setQuantity(detailVO.getBindableQuantity());
//                            ornm.setIsOutStock(Boolean.FALSE);
//                            ornm.setIsLock(Boolean.FALSE);
//                            ornmList.add(ornm);
//                            //对应订单号
//                            rnm.setOrderNo(impOrder.getDocNo());
//                        }
//                        receivingNoteMemberList.add(rnm);
//                    });
//
//                    //保存入库明细
//                    receivingNoteMemberService.savaBatch(receivingNoteMemberList);
//                    if(CollUtil.isNotEmpty(ornmList)){
//                        //保存订单绑定明细
//                        orderReceivingNoteMemberService.savaBatch(ornmList);
//                        //写入已绑定的订单
//                        receivingNote.setOrderNo(impOrder.getDocNo());
//                        super.updateById(receivingNote);
//                    }
//                }
            }

            //记录历史状态
            statusHistoryService.saveHistory(DomainOprationEnum.RECEIVING_ADD,
                    receivingNote.getId().toString(), ReceivingNote.class.getName(),
                    statusEnum.getCode(),statusEnum.getName(),
                    "入库登记"
            );
        }catch (DuplicateKeyException e) {
            if(e.getMessage().contains("UK_receiving_note_doc_no")) {
                throw new ServiceException("入库单号已经存在请修改");
            }else {
                log.error("保存失败：",e);
                throw new ServiceException("保存失败，请检查数据是否填写正确");
            }
        }
        return receivingNote.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveInspection(InspectionDTO dto) {
        ReceivingNote receivingNote = super.getById(dto.getId());
        TsfPreconditions.checkArgument(Objects.nonNull(receivingNote),new ServiceException("入库单不存在"));
        ReceivingMemberSaveDTO receivingMemberSaveDTO = receivingNoteMemberService.checkWrapReceivingMember(receivingNote,dto.getMembers());
        throw new ServiceException("测试");
    }

    @Override
    public List<SimpleReceivingNoteCartonVO> selectByReceivingNoteNo(String receivingNoteNo, Long customerId) {
        return receivingNoteMapper.selectByReceivingNoteNo(receivingNoteNo,customerId);
    }

    @Override
    public ReceivingNote findByDocNo(String docNo) {
        ReceivingNote query = new ReceivingNote();
        query.setDocNo(docNo);
        return receivingNoteMapper.selectOne(query);
    }

    @Override
    public PageInfo<ClientReceivingNoteVO> clientList(ClientReceivingNoteQTO qto) {
        PageHelper.startPage(qto.getPage(),qto.getLimit());
        qto.setCustomerId(SecurityUtil.getCurrentCustomerId());
        List<ClientReceivingNoteVO> list = receivingNoteMapper.clientList(qto);
        return new PageInfo<>(list);
    }
}
